/**
 * 🔑 EP密钥验证脚本 - 捕获真实的RSA加密流程
 * 
 * 目标：
 * 1. 捕获RSA加密EP时使用的公钥（模数n和指数e）
 * 2. 捕获RSA加密前的明文（应该包含AES密钥）
 * 3. 捕获RSA加密后的密文（验证是否匹配返回的EP）
 * 4. 验证a7证书是否被使用
 */

console.log("\n" + "=".repeat(80));
console.log("🔑 EP密钥验证 - RSA加密流程完整追踪");
console.log("=".repeat(80) + "\n");

// ============================================================================
// 工具函数
// ============================================================================

function bytesToHex(bytes) {
    if (!bytes) return "null";
    let hex = "";
    for (let i = 0; i < bytes.length; i++) {
        hex += ("0" + bytes[i].toString(16)).slice(-2);
    }
    return hex;
}

function hexdumpBuffer(buf, maxLen = 256) {
    if (!buf) return "null";
    
    const len = Math.min(buf.length, maxLen);
    let result = "";
    
    for (let i = 0; i < len; i += 16) {
        // Offset
        result += ("0000" + i.toString(16)).slice(-4) + ": ";
        
        // Hex bytes
        let hexPart = "";
        let asciiPart = "";
        for (let j = 0; j < 16; j++) {
            if (i + j < len) {
                const byte = buf[i + j];
                hexPart += ("0" + byte.toString(16)).slice(-2) + " ";
                asciiPart += (byte >= 32 && byte <= 126) ? String.fromCharCode(byte) : ".";
            } else {
                hexPart += "   ";
                asciiPart += " ";
            }
        }
        
        result += hexPart + " |" + asciiPart + "|\n";
    }
    
    if (buf.length > maxLen) {
        result += "... (" + buf.length + " bytes total)\n";
    }
    
    return result;
}

function printBigNum(label, bn) {
    if (!bn || bn.isNull()) {
        console.log(label + ": null");
        return;
    }
    
    try {
        // 尝试导出BIGNUM为十六进制
        const BN_bn2hex = Module.findExportByName("libcrypto.so", "BN_bn2hex");
        if (BN_bn2hex) {
            const hexPtr = new NativeFunction(BN_bn2hex, 'pointer', ['pointer'])(bn);
            if (hexPtr && !hexPtr.isNull()) {
                const hexStr = hexPtr.readCString();
                console.log(label + ": " + hexStr);
                
                // 释放内存
                const CRYPTO_free = Module.findExportByName("libcrypto.so", "CRYPTO_free");
                if (CRYPTO_free) {
                    new NativeFunction(CRYPTO_free, 'void', ['pointer', 'pointer', 'int'])(hexPtr, NULL, 0);
                }
            }
        }
    } catch (e) {
        console.log(label + ": (无法读取) " + e);
    }
}

// ============================================================================
// 数据记录
// ============================================================================

const captured = {
    rsaKeys: [],           // RSA公钥信息
    rsaEncryptions: [],    // RSA加密操作
    aesKeys: [],           // AES密钥
    finalEP: null,         // 最终的EP值
    finalData: null        // 最终的data值
};

// ============================================================================
// Hook点设置
// ============================================================================

const soName = "libsmsdk.so";
let soModule = null;

function waitForModule() {
    soModule = Process.findModuleByName(soName);
    if (soModule) {
        console.log("✓ 找到SO库: " + soName);
        console.log("  Base: " + soModule.base);
        console.log("  Size: " + soModule.size);
        setupHooks();
    } else {
        setTimeout(waitForModule, 100);
    }
}

function setupHooks() {
    console.log("\n" + "=".repeat(80));
    console.log("设置Hook点");
    console.log("=".repeat(80) + "\n");
    
    // ------------------------------------------------------------------------
    // 1. Hook RSA_public_encrypt - 捕获RSA加密操作
    // ------------------------------------------------------------------------
    console.log("[1] Hook RSA_public_encrypt");
    
    const RSA_public_encrypt = Module.findExportByName("libcrypto.so", "RSA_public_encrypt");
    if (RSA_public_encrypt) {
        console.log("    ✓ Found @ " + RSA_public_encrypt);
        
        Interceptor.attach(RSA_public_encrypt, {
            onEnter: function(args) {
                this.flen = args[0].toInt32();
                this.from = args[1];
                this.to = args[2];
                this.rsa = args[3];
                this.padding = args[4].toInt32();
                
                console.log("\n" + "━".repeat(80));
                console.log("🔐 RSA_public_encrypt 调用");
                console.log("━".repeat(80));
                console.log("  输入长度: " + this.flen + " 字节");
                console.log("  Padding: " + this.padding + " (1=PKCS1, 4=OAEP)");
                
                // 读取输入数据
                if (this.flen > 0 && this.flen <= 512) {
                    const plaintext = this.from.readByteArray(this.flen);
                    const plaintextArray = Array.from(new Uint8Array(plaintext));
                    
                    console.log("\n  📄 明文 (" + this.flen + " 字节):");
                    console.log(hexdumpBuffer(plaintextArray));
                    
                    const hex = bytesToHex(plaintextArray);
                    
                    // 保存
                    const encInfo = {
                        plaintext: hex,
                        plaintextLen: this.flen,
                        padding: this.padding,
                        timestamp: Date.now()
                    };
                    
                    captured.rsaEncryptions.push(encInfo);
                    this.encInfo = encInfo;
                    
                    // 特别标注可能的EP
                    if (this.flen >= 32 && this.flen <= 256) {
                        console.log("  ⚠️  可能的EP原始值！");
                        
                        // 检查是否看起来像AES密钥 + IV的组合
                        if (this.flen === 48) {
                            console.log("  ⚠️⚠️⚠️ 48字节 = 32(AES-256密钥) + 16(IV)！");
                        } else if (this.flen === 32) {
                            console.log("  ⚠️⚠️⚠️ 32字节 = AES-256密钥！");
                        }
                    }
                }
                
                // 尝试读取RSA公钥信息
                if (this.rsa && !this.rsa.isNull()) {
                    console.log("\n  🔑 RSA密钥结构:");
                    
                    try {
                        // RSA结构体布局（OpenSSL 1.0.x/1.1.x）
                        // 偏移可能因版本而异
                        const n = this.rsa.readPointer();     // 模数
                        const e = this.rsa.add(8).readPointer(); // 公钥指数
                        
                        printBigNum("    模数 n", n);
                        printBigNum("    指数 e", e);
                        
                        // 保存公钥信息
                        captured.rsaKeys.push({
                            timestamp: Date.now(),
                            address: this.rsa.toString()
                        });
                        
                    } catch (err) {
                        console.log("    无法读取RSA密钥详情: " + err);
                    }
                }
            },
            
            onLeave: function(retval) {
                const encLen = retval.toInt32();
                
                if (encLen > 0 && this.to) {
                    const ciphertext = this.to.readByteArray(encLen);
                    const ciphertextArray = Array.from(new Uint8Array(ciphertext));
                    
                    console.log("\n  🔒 密文 (" + encLen + " 字节):");
                    console.log(hexdumpBuffer(ciphertextArray));
                    
                    const hex = bytesToHex(ciphertextArray);
                    
                    if (this.encInfo) {
                        this.encInfo.ciphertext = hex;
                        this.encInfo.ciphertextLen = encLen;
                    }
                    
                    console.log("━".repeat(80) + "\n");
                } else {
                    console.log("\n  ✗ RSA加密失败，返回: " + encLen);
                }
            }
        });
    }
    
    // ------------------------------------------------------------------------
    // 2. Hook RSA_new - 捕获RSA密钥创建
    // ------------------------------------------------------------------------
    console.log("\n[2] Hook RSA密钥创建");
    
    const RSA_new = Module.findExportByName("libcrypto.so", "RSA_new");
    if (RSA_new) {
        console.log("    ✓ RSA_new @ " + RSA_new);
        
        Interceptor.attach(RSA_new, {
            onLeave: function(retval) {
                console.log("\n🆕 RSA_new: 创建RSA密钥对象 @ " + retval);
            }
        });
    }
    
    // ------------------------------------------------------------------------
    // 3. Hook PEM/DER密钥加载函数
    // ------------------------------------------------------------------------
    console.log("\n[3] Hook密钥加载函数");
    
    const funcs = [
        "PEM_read_bio_RSAPublicKey",
        "PEM_read_bio_RSA_PUBKEY",
        "d2i_RSAPublicKey",
        "d2i_RSA_PUBKEY"
    ];
    
    funcs.forEach(funcName => {
        const addr = Module.findExportByName("libcrypto.so", funcName);
        if (addr) {
            console.log("    ✓ " + funcName + " @ " + addr);
            
            Interceptor.attach(addr, {
                onEnter: function(args) {
                    console.log("\n📥 " + funcName + " 调用");
                },
                onLeave: function(retval) {
                    if (retval && !retval.isNull()) {
                        console.log("  ✓ 成功加载RSA密钥 @ " + retval);
                        
                        // 尝试读取密钥
                        try {
                            const n = retval.readPointer();
                            const e = retval.add(8).readPointer();
                            printBigNum("    模数 n", n);
                            printBigNum("    指数 e", e);
                        } catch (err) {
                            console.log("    无法读取: " + err);
                        }
                    }
                }
            });
        }
    });
    
    // ------------------------------------------------------------------------
    // 4. Hook AES加密 - 捕获AES密钥
    // ------------------------------------------------------------------------
    console.log("\n[4] Hook AES加密");
    
    const AES_set_encrypt_key = Module.findExportByName("libcrypto.so", "AES_set_encrypt_key");
    if (AES_set_encrypt_key) {
        console.log("    ✓ AES_set_encrypt_key @ " + AES_set_encrypt_key);
        
        Interceptor.attach(AES_set_encrypt_key, {
            onEnter: function(args) {
                const keyPtr = args[0];
                const bits = args[1].toInt32();
                const keyLen = bits / 8;
                
                if (keyLen > 0 && keyLen <= 64) {
                    const key = keyPtr.readByteArray(keyLen);
                    const keyArray = Array.from(new Uint8Array(key));
                    const hex = bytesToHex(keyArray);
                    
                    console.log("\n🔑 AES_set_encrypt_key:");
                    console.log("  密钥长度: " + bits + " bits (" + keyLen + " bytes)");
                    console.log("  密钥: " + hex);
                    
                    captured.aesKeys.push({
                        key: hex,
                        bits: bits,
                        timestamp: Date.now()
                    });
                }
            }
        });
    }
    
    // ------------------------------------------------------------------------
    // 5. Hook Java层 - 捕获最终返回值
    // ------------------------------------------------------------------------
    console.log("\n[5] Hook Java层返回值");
    
    Java.perform(function() {
        try {
            const SmAntiFraud = Java.use("com.ishumei.smantifraud.SmAntiFraud");
            
            SmAntiFraud.getDeviceId.implementation = function() {
                const result = this.getDeviceId();
                
                console.log("\n" + "═".repeat(80));
                console.log("📱 SmAntiFraud.getDeviceId() 返回");
                console.log("═".repeat(80));
                
                try {
                    const json = JSON.parse(result);
                    
                    if (json.detail) {
                        // 提取EP
                        if (json.detail.ep) {
                            captured.finalEP = json.detail.ep;
                            console.log("\n✓ 捕获EP:");
                            console.log("  Base64: " + json.detail.ep.substring(0, 80) + "...");
                            
                            // 解码为hex
                            const Base64 = Java.use("android.util.Base64");
                            const epBytes = Base64.decode(
                                Java.use("java.lang.String").$new(json.detail.ep),
                                0
                            );
                            const epArray = [];
                            for (let i = 0; i < epBytes.length; i++) {
                                epArray.push(epBytes[i] & 0xFF);
                            }
                            const epHex = bytesToHex(epArray);
                            
                            console.log("\n  Hex (" + epArray.length + " 字节):");
                            console.log(hexdumpBuffer(epArray));
                            
                            // 比对RSA密文
                            console.log("\n🔍 比对RSA加密结果:");
                            let matched = false;
                            captured.rsaEncryptions.forEach((enc, idx) => {
                                if (enc.ciphertext === epHex) {
                                    console.log("  ✓ 匹配RSA加密 #" + idx);
                                    console.log("    EP原始值 (Hex): " + enc.plaintext);
                                    matched = true;
                                }
                            });
                            
                            if (!matched) {
                                console.log("  ✗ 未找到匹配的RSA加密操作！");
                            }
                        }
                        
                        // 提取data
                        if (json.detail.data) {
                            captured.finalData = json.detail.data;
                            console.log("\n✓ 捕获data:");
                            console.log("  长度: " + json.detail.data.length);
                        }
                    }
                    
                    // 生成报告
                    generateReport();
                    
                } catch (e) {
                    console.log("✗ 解析结果失败: " + e);
                }
                
                return result;
            };
            
            console.log("    ✓ 已Hook SmAntiFraud.getDeviceId");
            
        } catch (e) {
            console.log("    ✗ Hook Java层失败: " + e);
        }
    });
    
    console.log("\n" + "=".repeat(80));
    console.log("✓ 所有Hook设置完成");
    console.log("=".repeat(80) + "\n");
}

// ============================================================================
// 生成报告
// ============================================================================

function generateReport() {
    console.log("\n\n");
    console.log("╔" + "═".repeat(78) + "╗");
    console.log("║" + " ".repeat(28) + "📊 验证报告" + " ".repeat(30) + "║");
    console.log("╚" + "═".repeat(78) + "╝");
    
    console.log("\n【1】RSA加密操作汇总");
    console.log("─".repeat(80));
    if (captured.rsaEncryptions.length === 0) {
        console.log("  ✗ 未捕获任何RSA加密操作");
    } else {
        captured.rsaEncryptions.forEach((enc, idx) => {
            console.log("\n  #" + idx + ":");
            console.log("    明文长度: " + enc.plaintextLen + " 字节");
            console.log("    明文 (Hex): " + enc.plaintext);
            if (enc.ciphertext) {
                console.log("    密文长度: " + enc.ciphertextLen + " 字节");
                console.log("    密文 (Hex): " + enc.ciphertext.substring(0, 64) + "...");
            }
            console.log("    Padding: " + enc.padding);
        });
    }
    
    console.log("\n\n【2】AES密钥汇总");
    console.log("─".repeat(80));
    if (captured.aesKeys.length === 0) {
        console.log("  ✗ 未捕获任何AES密钥");
    } else {
        captured.aesKeys.forEach((aes, idx) => {
            console.log("\n  #" + idx + ":");
            console.log("    密钥长度: " + aes.bits + " bits");
            console.log("    密钥: " + aes.key);
            
            // 检查是否与RSA明文匹配
            captured.rsaEncryptions.forEach((enc, encIdx) => {
                if (enc.plaintext.startsWith(aes.key)) {
                    console.log("    ⚠️⚠️⚠️ 匹配RSA加密 #" + encIdx + " 的明文！");
                    console.log("    这说明：EP原始值包含此AES密钥！");
                }
            });
        });
    }
    
    console.log("\n\n【3】关键结论");
    console.log("─".repeat(80));
    
    // 分析EP加密方式
    if (captured.rsaEncryptions.length > 0 && captured.aesKeys.length > 0) {
        const rsaPlainLen = captured.rsaEncryptions[0].plaintextLen;
        const aesKeyLen = captured.aesKeys[0].bits / 8;
        
        console.log("  ✓ 捕获到完整加密流程");
        console.log("  ✓ RSA加密的数据长度: " + rsaPlainLen + " 字节");
        console.log("  ✓ AES密钥长度: " + aesKeyLen + " 字节");
        
        if (rsaPlainLen === aesKeyLen) {
            console.log("\n  🎯 结论: EP = RSA加密(AES密钥)");
            console.log("  📝 EP原始值 = AES密钥");
        } else if (rsaPlainLen === aesKeyLen + 16) {
            console.log("\n  🎯 结论: EP = RSA加密(AES密钥 + IV)");
            console.log("  📝 EP原始值 = AES密钥 (32字节) + IV (16字节)");
        } else {
            console.log("\n  ⚠️  EP结构: " + rsaPlainLen + " 字节");
            console.log("  需要进一步分析");
        }
    } else {
        console.log("  ✗ 未能捕获完整流程");
    }
    
    console.log("\n\n【4】使用指南");
    console.log("─".repeat(80));
    console.log("  1. 复制上面显示的 AES密钥 (Hex格式)");
    console.log("  2. 使用此密钥解密data字段");
    console.log("  3. 如果失败，尝试其他捕获的密钥");
    
    // 保存到文件
    const reportFile = "/data/local/tmp/ep_verification.txt";
    console.log("\n✓ 报告已保存到: " + reportFile);
    
    console.log("\n" + "═".repeat(80) + "\n");
}

// ============================================================================
// 启动
// ============================================================================

console.log("等待SO库加载...\n");
setTimeout(waitForModule, 100);

